package com.ccbhelper.tranflows;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Date;
import java.util.Map;

public class JSONTool implements JsonSupport{
	private JSONTool(){
		  
	 }
	private static void convertMapToJson(Map map,
			   StringBuffer sb) {
			  sb.append(OBJ_START);
			  for(Object key : map.keySet()){
			   convertObjectToJson((String)key, map.get(key), sb);
			   sb.append(COMMA);
			  }
			  if(map.size() > 0){
				   sb.deleteCharAt(sb.length() - 1);
				  }				  
				  sb.append(OBJ_END);
				 }		
	private static void convertArrayToJson(Object[] arr, StringBuffer sb) {
		  sb.append(ARR_START);
		  for(Object val : arr){
		   convertObjectToJson(val, sb);
		   sb.append(COMMA);
		  }
		//remove the last comma
		  if(arr.length > 0){
		   sb.deleteCharAt(sb.length() - 1);
		  }
		  
		  sb.append(ARR_END);
		 }
	private static void insertClassDesc(StringBuffer sb, int offset, String key, String value){
		  StringBuffer mClassDesc = new StringBuffer();
		  
		  mClassDesc.append(D_QUOT);
		  mClassDesc.append(key);
		  mClassDesc.append(D_QUOT);
		  
		  mClassDesc.append(COLON);
		  
		  mClassDesc.append(D_QUOT);
		  mClassDesc.append(value);
		  mClassDesc.append(D_QUOT);
		  
		  mClassDesc.append(COMMA);
		  
		  sb.insert(offset, mClassDesc);
		 }
	private static void convertCollectionToJson(Collection mapVal, StringBuffer sb) {
		  sb.append(ARR_START);
		  for(Object val : mapVal){
		   convertObjectToJson(val, sb);
		   sb.append(COMMA);
		  }
		  
		  //remove the last comma
		  if(mapVal.size() > 0){
		   sb.deleteCharAt(sb.length() - 1);
		  }
		  
		  sb.append(ARR_END);
		 }
	private static void convertNumberToJson(Number obj, StringBuffer sb) {
		  sb.append(obj.toString());
		 }
	private static void convertBeanToJson(Object obj, StringBuffer sb){

		  sb.append(OBJ_START);
		  
		  Class c = obj.getClass();
		  insertClassDesc(sb, sb.length(), CLASS_FIELD, c.getName());
		  
		  if(obj instanceof Date){
		   
		   sb.append(D_QUOT);
		   sb.append(VALUE);
		   sb.append(D_QUOT);
		   
		   sb.append(COLON);
		   sb.append(((Date)obj).getTime());
		   
		  }else{
		   for(Field f : c.getDeclaredFields()){
		    
		    if(f.isEnumConstant() || 
		     Modifier.isFinal(f.getModifiers()) || 
		     Modifier.isTransient(f.getModifiers())){
		     continue;
		    }
		    
		    f.setAccessible(true);
		    try {
		     convertObjectToJson(f.getName(), f.get(obj), sb);
		    } catch (IllegalArgumentException e) {
		     // skip any error
		    } catch (IllegalAccessException e) {
		     // skip any error
		    }
		    sb.append(COMMA);
		   }
		   
		   if(sb.charAt(sb.length() - 1) == COMMA){
		    sb.deleteCharAt(sb.length() - 1);
		   }
		  }
		  
		  sb.append(OBJ_END);
		 }
	private static void convertObjectToJson(Object obj, StringBuffer sb){
		  convertObjectToJson(obj, sb, null);
		 }
	@SuppressWarnings("unchecked")
	 private static void convertObjectToJson(Object obj, StringBuffer sb, String key){
	  
	  if(obj == null){
	   sb.append(STATIC_VALUE_NULL);
	  }else if(obj instanceof Map){
	   
	   if(key != null){
	    insertClassDesc(sb, sb.length() - key.length() - 3, MAP_CLASS_PFRIEX + key, obj.getClass().getName());
	   }
	   
	   Map mapVal = (Map)obj;
	   convertMapToJson(mapVal, sb);
	  }else if(obj instanceof Collection){
	   if(key != null){
	    insertClassDesc(sb, sb.length() - key.length() - 3, COLLECTION_CLASS_PFRIEX + key, obj.getClass().getName());
	   }
	   
	   Collection mapVal = (Collection)obj;
	   convertCollectionToJson(mapVal, sb);
	  }else if(obj instanceof Object[]){
	   convertArrayToJson((Object[])obj, sb);
	  }else if(obj instanceof Number){
	   convertNumberToJson((Number)obj, sb);
	  }else if(obj instanceof Character){
	   sb.append((Character)obj);
	  }else if(obj instanceof Boolean){
	   sb.append(obj.toString());
	  }else if(obj instanceof CharSequence){
	   sb.append(D_QUOT);
	   sb.append(obj.toString().replace(QUOT_STR, QUOT_STR_REP));
	   sb.append(D_QUOT);
	  }else{
	   convertBeanToJson(obj, sb);
	  }
	 }
	private static void convertObjectToJson(String key, Object obj, StringBuffer sb){
		  
		  key = key.replace(QUOT_STR, QUOT_STR_REP);
		  
		  sb.append(D_QUOT);
		  sb.append(key);
		  sb.append(D_QUOT);
		  sb.append(COLON);
		  
		  convertObjectToJson(obj, sb, key);
		 }
	public static String convertObjectToJson(Object o){
		  StringBuffer sb = new StringBuffer();
		  convertObjectToJson(o, sb);
		  return sb.toString();
		 }
	public static Object convertJsonToObject(String jsonStr){
		  return JSONUtil.parse(jsonStr);
		 }
}
